package ca.ualberta.cs.CLRServer.resources;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import uk.ac.liv.c3connector.AnnotationModel;
import uk.ac.liv.c3connector.DistributedPersonalAnnos;
import ca.ualberta.cs.CLRDB.User;
import ca.ualberta.cs.CLRServer.Interface.SecureResource;
import ca.ualberta.cs.CLRServer.Interface.ServerInterface;

@Path("/searchService")
public class SearchAnnotations extends SecureResource{

	//@Path("/sameUrl")
	@POST 
    @Consumes("text/plain")
    @Produces("application/json")
    public List<JAXBBean> searchResourceUri(String resourceUri){
		
		checkUrl(resourceUri);
		
		/*System.out.println("somebody searching for annotations of this resource: "+resourceUri);
		System.out.println();*/
    	
		List<JAXBBean> annoBeans = new ArrayList<JAXBBean>();
		
		ArrayList<AnnotationModel> annos = ServerInterface.db.annoMgmt.findAnnosWithResourceUri(resourceUri);
		for(AnnotationModel am : annos ){
			JAXBBean bean = new JAXBBean();
			
			try {
				bean.setKey( ServerInterface.ams.serialise(am) );			
				annoBeans.add(bean);		
			} catch (Exception e) {
				System.err.println("problem with serialising the annotation, retreived from database, searched by resourceUri: "+ resourceUri);
				e.printStackTrace();
			}
		}
				
    	return annoBeans;
    }
	
	@Path("/sameBib")
	@POST 
    @Consumes("text/plain")
    @Produces("application/json")
    public List<JAXBBean> searchResourceBib(String resourceUri){
		
		checkUrl(resourceUri);
		
		/*System.out.println("somebody searching for annotations of resources with same bib with resource: "+resourceUri);
		System.out.println();*/
    	
		List<JAXBBean> annoBeans = new ArrayList<JAXBBean>();
		
		ArrayList<AnnotationModel> annos = ServerInterface.db.annoMgmt.findAnnosWithSameBib(resourceUri);
		for(AnnotationModel am : annos ){
			JAXBBean bean = new JAXBBean();
			try {
				bean.setKey( ServerInterface.ams.serialise(am) );			
				annoBeans.add(bean);
				
			} catch (Exception e) {
				System.err.println("problem with serialising the annotation, retreived from database, searched by resourceUri: "+ resourceUri);
				e.printStackTrace();
			}
		}
				
    	return annoBeans;
    }
	
	@Path("/allTags")
	@POST 
    @Consumes("text/plain")
    @Produces("application/json")
    public List<JAXBBean> searchResourceTags(String resourceUri){
    	
		checkUrl(resourceUri);
		
//		System.out.println("somebody requesting to see all tags of resource: "+resourceUri);
//		System.out.println();
		
		List<JAXBBean> annoBeans = new ArrayList<JAXBBean>();
		
		ArrayList<String> tags = ServerInterface.db.getResourceManagement().getTagsManagement().findResourceTagsByURL(resourceUri,null);
		
		if(true){ //TODO: change to: if(DistributedPersonalAnnos.sameDigest, ....
			ArrayList<String> tags2 = ServerInterface.db.getResourceManagement().getTagsManagement().findResourceTagsByDigestAndBib(resourceUri,null);
			for(String tag: tags2)
				if(!tags.contains(tag.trim()) && !tags.contains(tag))
					tags.add(tag.trim());
		}
		
		for(String tag : tags ){
			JAXBBean bean = new JAXBBean();			
			bean.setKey( tag );			
			annoBeans.add(bean);
		}
				
		
    	return annoBeans;
    }
	
	@Path("/tagsByUrl")
	@POST 
    @Consumes("text/plain")
    @Produces("application/json")
    public List<JAXBBean> tagCloudByUrl(String resourceUri){
    	
		checkUrl(resourceUri);
		
//		System.out.println("somebody requesting to see all tags of resource: "+resourceUri);
//		System.out.println();
		
		return getTagCloud(SearchCriteria.SameUrl, resourceUri);
    }
	
	@Path("/tagsByDigest")
	@POST 
    @Consumes("text/plain")
    @Produces("application/json")
    public List<JAXBBean> tagCloudByDigest(String resourceUri){
    	
		checkUrl(resourceUri);
		
//		System.out.println("somebody requesting to see all tags of resource: "+resourceUri);
//		System.out.println();
		
		return getTagCloud(SearchCriteria.SameDigest, resourceUri);
    }
	

	@Path("/tagsByBib")
	@POST 
    @Consumes("text/plain")
    @Produces("application/json")
    public List<JAXBBean> tagCloudByBib(String resourceUri){
    	
		checkUrl(resourceUri);
		
//		System.out.println("somebody requesting to see all tags of resource: "+resourceUri);
//		System.out.println();
		
		return getTagCloud(SearchCriteria.SameBib, resourceUri);
    }

	private List<JAXBBean> getTagCloud(SearchCriteria criteria, String resourceUri){
		HashMap<String,Integer> tags = new HashMap<String, Integer>();
		List<JAXBBean> annoBeans = new ArrayList<JAXBBean>();
		
		if( criteria == SearchCriteria.SameUrl)
			tags = ServerInterface.db.getResourceManagement().getTagsManagement().tagCloudByUrl(resourceUri);
		if( criteria == SearchCriteria.SameBib)
			tags = ServerInterface.db.getResourceManagement().getTagsManagement().tagCloudBySameBib(resourceUri);
		if( criteria == SearchCriteria.SameDigest)
			tags = ServerInterface.db.getResourceManagement().getTagsManagement().tagCloudBySameDigest(resourceUri);
		
		for(String tag : tags.keySet() ){
			JAXBBean bean = new JAXBBean();			
			bean.setKey(tag); //label as key
			bean.setVal(tags.get(tag).toString()); //count as value
			annoBeans.add(bean);
		}
		
		return annoBeans;
	}
	
	@Path("/checksum")
	@POST 
    @Consumes("application/json")
    @Produces("application/json")
    public List<JAXBBean> searchResourceChecksum(List<JAXBBean> requestArr){
		
		checkBufferOverflow(requestArr,3);
		checkRequiredKeys(requestArr, "method","checksum","encoding");
		
		/*System.out.println("somebody searching for annotations of resources with same checksum ");
		System.out.println();*/
    	
		String checksum = "";
		String method = "";
    	String encoding = "";    	
    	
    	for(int i = 0 ; i < requestArr.size() ; i++ ){
    		if( requestArr.get(i).getKey().equals("method") )
    			method = requestArr.get(i).getVal();
    		else if( requestArr.get(i).getKey().equals("checksum") )
    			checksum = requestArr.get(i).getVal();
    		else if( requestArr.get(i).getKey().equals("encoding") )
    			encoding = requestArr.get(i).getVal();
    	}
		
		List<JAXBBean> annoBeans = new ArrayList<JAXBBean>();
		
		ArrayList<AnnotationModel> annos = new ArrayList<AnnotationModel>();
		
		if(method.equals("MD5") && encoding.equals("base64"))
			annos = ServerInterface.db.annoMgmt.findAnnosWithSameMd5Base64(checksum);
		else if(method.equals("multivalent annotation") && encoding.equals("base64-MD5-text"))
			annos = ServerInterface.db.annoMgmt.findAnnosWithSameMultivalentBase64Md5Text(checksum);
		
		for(AnnotationModel am : annos ){
			JAXBBean bean = new JAXBBean();
			try {
				bean.setKey( ServerInterface.ams.serialise(am) );			
				annoBeans.add(bean);
				
			} catch (Exception e) {
				System.err.println("problem with serialising the annotation, retreived from database, searched by checksum ");
				e.printStackTrace();
			}
		}
				
    	return annoBeans;
    }
    
}
